package com.vatata.wae.jsobject.Media;

import android.annotation.TargetApi;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;

import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.upstream.FileDataSource;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener;
import com.vatata.wae.jsobject.UI.IView;
import com.vatata.wae.jsobject.WAE.MessageManager;

import static com.google.android.exoplayer2.C.TRACK_TYPE_AUDIO;

public class VideoPlayer3 extends IView {
//    private static int logEnabled = -1;
//    private static final String VTAG = "VideoPlayerKTV";
//
//    public static void log(String msg) {
//        if (logEnabled == -1) {
//            logEnabled = 0;
//            try {
//                File logVideoPlayer = new File("/sdcard/tva/log.videoplayer");
//                if (logVideoPlayer.exists())
//                    logEnabled = 1;
//            } catch (Exception e) {
//            }
//            if (WaeWebChromeClient.isOutputConsoleMessage) {
//                logEnabled = 1;
//            }
//            Log.d(VTAG, "logEnabled: " + logEnabled);
//        }
//        if (logEnabled == 0)
//            return;
//
//        Log.d(VTAG, msg);
//    }

    public void destory() {
        log("VideoPlayer destroy!");
        if (player != null) {
            player.release();
            player = null;
        }
    }

    boolean _has_destroied() {
        if (view == null || view.activity == null) return true;
        return false;
    }

    void _runOnPlayer(Runnable r) {
        view.activity.runOnUiThread(r);
//		playerHandler.post(r);
    }

    void _runOnUI(Runnable r) {
        view.activity.runOnUiThread(r);
    }

    @Override
    public void _create() {
        _runOnPlayer(new Runnable() {

            @Override
            public void run() {
                try {
                    iview = initVideoView();

                } catch (Exception e) {
                    log("initVideoView meet : " + e.getLocalizedMessage());
                    e.printStackTrace();
                    return;
                }
                if (iview == null) return;

                MessageManager.sendMessage(view, objectId, "Created");
            }
        });
    }

    SimpleExoPlayer player = null;
    Player.EventListener eventListener = null;
    boolean playWhenReady = true;
    private static final DefaultBandwidthMeter BANDWIDTH_METER =
            new DefaultBandwidthMeter();
    DefaultTrackSelector trackSelector;

    String userAgent = "";

    boolean hasPrePrared = false;

    SurfaceView mSurfaceView;

    private View initVideoView() {
        mSurfaceView = new SurfaceView( view.activity );
        mSurfaceView.setFocusable(false);
        mSurfaceView.setFocusableInTouchMode(false);

        SurfaceHolder holder = mSurfaceView.getHolder();
//	    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//	    holder.setFormat(PixelFormat.RGBX_8888);

        holder.addCallback( new SurfaceHolder.Callback(){

            @Override
            public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
                                       int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void surfaceCreated(SurfaceHolder holder ) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder arg0) {
                // TODO Auto-generated method stub

            }} );

        mSurfaceView.setZOrderMediaOverlay(true);
        mSurfaceView.setZOrderOnTop(false);

        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(100, 100);
        view.activity.getRootView().addView(mSurfaceView, lp);

        if (player == null) {
            userAgent = Util.getUserAgent(view.activity, "TVA EVideoPlayer");

            AdaptiveTrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory();
            trackSelector = new DefaultTrackSelector( view.activity, trackSelectionFactory);
            DefaultRenderersFactory renderersFactory =
                    new DefaultRenderersFactory(view.activity, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER);
            SimpleExoPlayer.Builder builder = new SimpleExoPlayer.Builder( view.activity.getApplicationContext()  , renderersFactory );

            builder.setTrackSelector( trackSelector );
            player = builder.build();

            eventListener = new Player.EventListener(){

                public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                    switch ( playbackState) {
                        case Player.STATE_READY:
                            log("STATE_READY"  );

                            if ( hasPrePrared == false ) {
                                hasPrePrared = true;
                                MessageManager.sendMessage(view, objectId,
                                        "Prepared",
                                        url, getDuration(), getVolume() );
                            }

                            MessageManager.sendMessage(view, objectId, "BufferingUpdate",
                                    url, 100 , "ready");
                            break;
                        case Player.STATE_BUFFERING:
                            log("STATE_BUFFERING"  );
                            MessageManager.sendMessage(view, objectId, "BufferingUpdate",
                                    url, 0 , "buffering");
                            break;
                        case Player.STATE_ENDED:
                            log("STATE_ENDED"  );
                            MessageManager.sendMessage(view, objectId,
                                    "Completion", url);
                            break;
                    }
                }

                public void onPlayerError(ExoPlaybackException error) {
                    log("onPlayError" + error.toString() );
//                    Toast.makeText(view.activity, error.toString() , Toast.LENGTH_LONG ).show();
                    MessageManager.sendMessage(view, objectId,
                            "Error", url, error.toString() );
                }
            };
            player.addListener( eventListener );

            player.addVideoListener(new VideoListener() {
                @Override
                public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
                    log("video size change " + width + "x" + height);
                }

                @Override
                public void onSurfaceSizeChanged(int width, int height) {
                    log("sufacesize change: " + width + "x" + height );
                }

                @Override
                public void onRenderedFirstFrame() {
                    log("render start ...");
                }
            });
        }

        player.setVideoSurfaceView( mSurfaceView );
        player.setPlayWhenReady(playWhenReady);

        return mSurfaceView;
    }


    public static boolean force1080pfullscreen = true;

    boolean isFullscreen = false;

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    public void setFullScreen() {
        log("setFullScreen isFullscreen : " + isFullscreen + " isvisbile : " + iview.getVisibility() );
        if (isFullscreen == true &&iview.getVisibility() == View.VISIBLE  ) {
            return;
        }

        if ( force1080pfullscreen == true ) {
            this.move(0,0,1920,1080);
            isFullscreen = true;
            return;
        }

        _runOnUI(new Runnable() {

            @Override
            public void run() {
                if ( iview.getVisibility() != View.VISIBLE ) {
                    iview.setVisibility(View.VISIBLE );
                }

//                DisplayMetrics metrics = new DisplayMetrics();
//                view.activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
//                final int nw = metrics.widthPixels;
//                final int nh = metrics.heightPixels;

                int nw = FrameLayout.LayoutParams.MATCH_PARENT;
                int nh = FrameLayout.LayoutParams.MATCH_PARENT;

//                nw = 1920;
//                nh = 1080;

                log("setFullScreen: " + nw + "x" + nh);
                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) iview.getLayoutParams();
                if (lp == null) {
                    lp = new FrameLayout.LayoutParams(nw, nh);
                }
                lp.leftMargin = 0;
                lp.topMargin = 0;
                lp.height = nh;
                lp.width = nw;


                if ( iview.getVisibility() != View.VISIBLE ) {
                    iview.setLayoutParams(lp);
                    iview.setVisibility(View.VISIBLE);
                } else {
                    iview.setLayoutParams(lp);
                }

//                mSurfaceView.getHolder().setSizeFromLayout();
                isFullscreen = true;
            }
        });
    }

    public void keepScreenOn() {
        view.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    String url = null;

    public void setDataSource(final String murl) {
        log("setDataSource " + murl );
//        log("setDataSource when playerview is getVisibility " + iview.getVisibility() );
        if (_has_destroied()) {
            log("setDataSource since mediaplayer has be destoried!");
            return;
        }

        if ( iview.getVisibility() != View.VISIBLE ) {
            view.activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    iview.setVisibility(View.VISIBLE);
                }
            });
        }
        url = murl;

        Uri uri = Uri.parse(murl);
        MediaSource mediaSource = null;
        if (murl.contains(".m3u8")) {
            DefaultDataSourceFactory upstreamFactory =new DefaultDataSourceFactory( view.activity, userAgent );
            mediaSource = new ProgressiveMediaSource.Factory(upstreamFactory).
                    createMediaSource(MediaItem.fromUri(uri));
        } else if ( murl.contains("file://")  ) {
            FileDataSource fileDataSource = new FileDataSource();
            try {
                DefaultDataSourceFactory upstreamFactory =new DefaultDataSourceFactory( view.activity, userAgent );
                mediaSource = new ProgressiveMediaSource.Factory(upstreamFactory).
                        createMediaSource(MediaItem.fromUri(uri));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else {
            DefaultDataSourceFactory upstreamFactory =new DefaultDataSourceFactory( view.activity, userAgent );
            mediaSource = new ProgressiveMediaSource.Factory(upstreamFactory).
                    createMediaSource(MediaItem.fromUri(uri));
        }

        mappedTrackInfo = null;
        hasPrePrared = false;

        final MediaSource mediaSource2 = mediaSource;

        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                player.prepare(mediaSource2);
                player.setPlayWhenReady(true);

//                MessageManager.sendMessage(view, objectId,
//                        "Prepared",
//                        url, getDuration(), getVolume() );
            }
        });
    }

    public void start() {
        if (_has_destroied()) return;

        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                player.setPlayWhenReady(true);
                player.getPlaybackState();
            }
        });
    }

    public void pause() {
        if (_has_destroied()) return;
        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                player.setPlayWhenReady(false);
                player.getPlaybackState();
            }
        });
    }

    public void stop() {
        if (_has_destroied()) return;
        player.stop();
//        log("stop and hide");
//        this.hide();
    }

    public void seekTo( final int msec ) {
        if (_has_destroied()) return;
        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                player.seekTo( msec );
            }
        });
    }

    public boolean isPlaying() {
        int state = player.getPlaybackState();
        if ( player.getPlayWhenReady() == true && state == Player.STATE_READY ) return true;
        return false;
    }

    public int getCurrentPosition() {
        if ( _has_destroied() ) return -1;

        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if( player == null ) return;
                float d = player.getDuration();
                float t = player.getCurrentPosition();
                MessageManager.sendMessage(view, objectId,
                        "Play", d, t );
            }
        });

        return 0;
//        return (int) player.getCurrentPosition();
    }
    public int getDuration() {
        if ( _has_destroied() ) return -1;
//        return (int) player.getDuration();
        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if( player == null ) return;
                float d = player.getDuration();
                float t = player.getCurrentPosition();
                MessageManager.sendMessage(view, objectId,
                        "Play", d, t );
            }
        });

        return 0;
    }

    public float getVolume() {
        int cvol= view.activity.application.audioManager
                .getStreamVolume(AudioManager.STREAM_MUSIC);

        int mvol= view.activity.application.audioManager
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        return cvol *1.0f / mvol;
    }


    public void setVolume( float vol ) {
        int mvol= view.activity.application.audioManager
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        int cvol =(int)( mvol * vol);
        view.activity.application.audioManager
                .setStreamVolume(AudioManager.STREAM_MUSIC, cvol, 0);
    }


    public void setMute( boolean isMute ) {
        view.activity.application.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, isMute);
    }


//    public void setStereoVolume( float l, float r ) {
//        player.setau
//    }


    float speed = 1f;
    float pitch = 1f;
    public void setPlaySpeed( float speed ) {
        log("setPlaySpeed :" + speed );
        this.speed = speed;
        PlaybackParameters param = new PlaybackParameters(speed, pitch);
        player.setPlaybackParameters(param);
    }

    public void setPlayPitch( float pitch ) {
        log("setPlayPitch: " + pitch);
        if (_has_destroied()) return;
        this.pitch = pitch;
        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                PlaybackParameters param = new PlaybackParameters(speed, pitch);
                player.setPlaybackParameters(param);
            }
        });
    }

    public void setPlayEffects( float speed, float pitch ) {
        this.speed = speed;
        this.pitch = pitch;
        view.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                PlaybackParameters param = new PlaybackParameters(speed, pitch);
                player.setPlaybackParameters(param);
            }
        });
    }

    public float getSpeed() {
        return speed;
    }
    public float getPitch() {
        return pitch;
    }



    //    ArrayList<String> langList = new ArrayList<String>();
    MappingTrackSelector.MappedTrackInfo mappedTrackInfo = null;
    int rederIdx = -1;
    public int getAudioTrack() {
        if ( player == null ) return -1;

        mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
        if ( mappedTrackInfo== null ) return -1;

        int c = mappedTrackInfo.getRendererCount();
        for( int i=0; i<c; i++ ) {
            int type = mappedTrackInfo.getRendererType(i);
            if ( type != TRACK_TYPE_AUDIO ) continue;

            rederIdx = i;
//            log("found TRACK_TYPE_AUDIO  idx is  " + i );
            int total = 0;
            TrackGroupArray trackGroupList = mappedTrackInfo.getTrackGroups(i);
            for( int j = 0; j<trackGroupList.length; j++  ) {
                TrackGroup trackGroup = trackGroupList.get(j);
//                log("found TrackGroup " + j + " : " + trackGroup );
                for(int k =0; k<trackGroup.length; k++ ) {
                    Format format = trackGroup.getFormat(k);
                    log("get format " + format );
                    String mimeType = format.sampleMimeType;
                    log("getAudioTrack: trackGroup: " + trackGroup.toString() );
                    log("getAudioTrack: format    : " + format.toString() );
                    log("getAudioTrack: format.mimeType    : " + format.sampleMimeType );
                    log("getAudioTrack: format.id    : " + format.id );
                    log("getAudioTrack: format.lang    : " + format.language );

                    total ++;
                }
            }
            return total;
        }

        return -1;
    }

    public void setAudioTrackByIdx( final int idx ) {
        if ( player == null )
            return;

        if ( trackSelector == null )
            return;

        if ( mappedTrackInfo == null )
            getAudioTrack();
        if ( mappedTrackInfo == null )
            return;

        DefaultTrackSelector.ParametersBuilder parametersBuilder = trackSelector.buildUponParameters().setSelectionOverride(
                rederIdx,
                mappedTrackInfo.getTrackGroups(rederIdx),
                new DefaultTrackSelector.SelectionOverride(idx, 0)
        );

        trackSelector.setParameters( parametersBuilder );

//        if ( idx < 0 || idx >= langList.size() ) {
//            log("setAudioTrackByIdx " + idx + " ? max size: " + langList.size() );
//            return;
//        }
//
//        String lang = langList.get(idx);
//        log("setAudioTrackByName " + lang );
//
//        new DefaultTrackSelector.SelectionOverride(0, 0);
//
//        trackSelector.setParameters( trackSelector.getParameters().buildUpon().setPreferredAudioLanguage(lang));
    }
}

